/*
 * Copyright © 2009-2020 Frictional Games
 * 
 * This file is part of Amnesia: The Dark Descent.
 * 
 * Amnesia: The Dark Descent is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version. 

 * Amnesia: The Dark Descent is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Amnesia: The Dark Descent.  If not, see <https://www.gnu.org/licenses/>.
 */

#include "EditorVar.h"
#include "EditorWindow.h"

//--------------------------------------------------------------------


//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR BASE
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVar::iEditorVar(eVariableType aType)
{
	mType = aType;
	mpExtData = NULL;
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

bool iEditorVar::Create(cXmlElement* apElement)
{
	if(apElement==NULL)
		return false;

	msName = cString::To16Char(apElement->GetAttributeString("Name"));
	if(msName==_W(""))
		return false;

	msDefaultValue = cString::To16Char(apElement->GetAttributeString("DefaultValue"));
	msDescription = cString::To16Char(apElement->GetAttributeString("Description"));

	if(msDefaultValue==_W(""))
		msDefaultValue = cString::To16Char(apElement->GetAttributeString("Value"));

	return true;
}

//--------------------------------------------------------------------------------

iEditorVarInput* iEditorVar::CreateInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	iEditorVarInput* pInput = CreateSpecificInput(apWindow, apParent, apVar);
	if(pInput)
	{
		iEditorInput* pEditorInput = pInput->GetInput();
		pEditorInput->SetLayoutStyle(eEditorInputLayoutStyle_RowLabelOnLeft);
		pEditorInput->UpdateLayout();
	}

	return pInput;
}

//--------------------------------------------------------------------------------

cEditorVarInstance* iEditorVar::CreateInstance()
{
	cEditorVarInstance* pInstance = hplNew(cEditorVarInstance,(this));
	pInstance->SetValue(msDefaultValue);

	return pInstance;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR INPUT BASE
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput::iEditorVarInput(cEditorVarInstance* apVar, iEditorInput* apInput)
{
	mpVar = apVar; 
	mpInput = apInput;
	mpPanel = NULL;

	mpInput->AddCallback(eEditorInputCallback_ValueEnter, this, kGuiCallback(OnValueEnter));
	mpInput->GetHandle()->SetToolTip(apVar->GetVarType()->GetDescription());
}

iEditorVarInput::~iEditorVarInput()
{
	iEditorWindow* pWindow = mpInput->GetWindow();
	pWindow->DestroyInput(mpInput);
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

void iEditorVarInput::Update()
{
	FetchValueFromVar();
}

//--------------------------------------------------------------------------------

void iEditorVarInput::FetchValueFromVar()
{
	mpInput->SetValue(mpVar->GetValue(), false);
}

//--------------------------------------------------------------------------------

void iEditorVarInput::CopyValueToVar()
{
	mpVar->SetValue(mpInput->GetValue());
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

bool iEditorVarInput::OnValueEnter(iWidget* apWidget, const cGuiMessageData& aData)
{
	if(mpPanel->RunCallback(this)==false)
        CopyValueToVar();

	return true;
}
kGuiCallbackDeclaredFuncEnd(iEditorVarInput,OnValueEnter);

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR BOOL
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarBool::cEditorVarBool() : iEditorVar(eVariableType_Bool)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarBool::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputBool,(apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR BOOL INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputBool::cEditorVarInputBool(cEditorVarInstance* apVar, 
										 iEditorWindow* apWindow, 
										 iWidget* apParent) : iEditorVarInput(apVar,
																			  apWindow->CreateInputBool(0,apVar->GetVarType()->GetName(), 
																										"", 
																										apParent))
{
}


//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR FLOAT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarFloat::cEditorVarFloat() : iEditorVar(eVariableType_Float)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarFloat::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputFloat,(apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR FLOAT INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputFloat::cEditorVarInputFloat(cEditorVarInstance* apVar,
										   iEditorWindow* apWindow,
										   iWidget* apParent) : iEditorVarInput(apVar, 
																				apWindow->CreateInputNumber(0,
																											apVar->GetVarType()->GetName(),
																											"",
																											apParent,
																											50,0.1f))
{
}
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR INT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInt::cEditorVarInt() : iEditorVar(eVariableType_Int)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarInt::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputInt, (apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR INT INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputInt::cEditorVarInputInt(cEditorVarInstance* apVar,
									   iEditorWindow* apWindow,
									   iWidget* apParent) : iEditorVarInput(apVar,
																			apWindow->CreateInputNumber(0,apVar->GetVarType()->GetName(), "", apParent, 50, 1))
{
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR STRING
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarString::cEditorVarString() : iEditorVar(eVariableType_String)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarString::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputString, (apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR STRING INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputString::cEditorVarInputString(cEditorVarInstance* apVar,
											 iEditorWindow* apWindow,
											 iWidget* apParent) : iEditorVarInput(apVar,
																				  apWindow->CreateInputString(0,apVar->GetVarType()->GetName(), "", apParent, 160))
																									
{
}


//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR VECTOR2F
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarVector2f::cEditorVarVector2f() : iEditorVar(eVariableType_Vec2)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarVector2f::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputVector2f, (apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR VECTOR2F INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputVector2f::cEditorVarInputVector2f(cEditorVarInstance* apVar,
												 iEditorWindow* apWindow,
												 iWidget* apParent) : iEditorVarInput(apVar,
																					  apWindow->CreateInputVec2(0,apVar->GetVarType()->GetName(), 
																												"", apParent, 50, tWStringList(),eEditorInputLayoutStyle_RowLabelOnTop, 0.1f))
{
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR VECTOR3F
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarVector3f::cEditorVarVector3f() : iEditorVar(eVariableType_Vec3)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarVector3f::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputVector3f, (apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR VECTOR3F INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputVector3f::cEditorVarInputVector3f(cEditorVarInstance* apVar,
												 iEditorWindow* apWindow,
												 iWidget* apParent) : iEditorVarInput(apVar,
																					  apWindow->CreateInputVec3(0,apVar->GetVarType()->GetName(), "", apParent,50,tWStringList(), eEditorInputLayoutStyle_RowLabelOnTop, 0.1f))
{
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR COLOR
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarColor::cEditorVarColor() : iEditorVar(eVariableType_Color)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarColor::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputColor, (apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR COLOR INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputColor::cEditorVarInputColor(cEditorVarInstance* apVar,
										   iEditorWindow* apWindow,
										   iWidget* apParent) : iEditorVarInput(apVar,
																				apWindow->CreateInputColorFrame(0, apVar->GetVarType()->GetName(), "", apParent))
{
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR ENUM
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarEnum::cEditorVarEnum() : iEditorVar(eVariableType_Enum)
{
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarEnum::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	return hplNew(cEditorVarInputEnum, (apVar, apWindow, apParent));
}

//--------------------------------------------------------------------------------

bool cEditorVarEnum::Create(cXmlElement* apElement)
{
	if(iEditorVar::Create(apElement)==false)
		return false;

	int lCurrentValue=-1;

	int i=0;
	cXmlNodeListIterator it = apElement->GetChildIterator();
	while(it.HasNext())
	{
		cXmlElement* pValue = it.Next()->ToElement();
		tWString sValue = cString::To16Char(pValue->GetAttributeString("Name"));

		if(msDefaultValue==sValue)
			lCurrentValue = i;
		mvValues.push_back(sValue);

		++i;
	}

	if(lCurrentValue==-1 && mvValues.empty()==false)
		msDefaultValue = mvValues[0];

	return true;
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR ENUM INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputEnum::cEditorVarInputEnum(cEditorVarInstance* apVar,
										 iEditorWindow* apWindow,
										 iWidget* apParent) : iEditorVarInput(apVar,
																			  apWindow->CreateInputEnum(0, apVar->GetVarType()->GetName(), "", tWStringList(), apParent))
{
	cEditorInputEnum* pInput = (cEditorInputEnum*)mpInput;
	cEditorVarEnum* pEnum = (cEditorVarEnum*)apVar->GetVarType();

	const tWStringVec& vValues = pEnum->GetEnumValues();
	for(int i=0;i<(int)vValues.size();++i)
		pInput->AddValue(vValues[i]);

	mpInput->SetValue(mpVar->GetValue(), false, true);
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// EDITOR VAR FILE
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarFile::cEditorVarFile() : iEditorVar(eVariableType_String)
{
}

//--------------------------------------------------------------------------------

bool cEditorVarFile::Create(cXmlElement* apElement)
{
	if(iEditorVar::Create(apElement)==false)
		return false;

	mResType = GetBrowserTypeFromElement(apElement);
	if(mResType==eEditorResourceType_LastEnum)
	{
		tString sExtensions = apElement->GetAttributeString("Extensions");
		tStringVec vExtensions;
		vExtensions = cString::GetStringVec(sExtensions, vExtensions);
		for(int i=0;i<(int)vExtensions.size();++i)
			mlstExtensions.push_back(cString::To16Char(vExtensions[i]));
	}

	return true;
}

//--------------------------------------------------------------------------------

eEditorResourceType cEditorVarFile::GetBrowserTypeFromElement(cXmlElement* apElement)
{
	tString sType = apElement->GetAttributeString("ResType", "Custom");

	tString vResStrings[] = 
	{
		"Material",
		"Texture",
		"Sound",
		"ParticleSystem",
		"Entity",
		"Model",

		""
	};

	for(int i=0;vResStrings[i]!="";++i)
	{
		const tString& sResType = vResStrings[i];
		if(sType==sResType)
			return (eEditorResourceType)i;
	}

	return eEditorResourceType_LastEnum;
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

iEditorVarInput* cEditorVarFile::CreateSpecificInput(iEditorWindow* apWindow, iWidget* apParent, cEditorVarInstance* apVar)
{
	cEditorVarInputFile* pInput = hplNew(cEditorVarInputFile, (apVar, apWindow, apParent));
	cEditorInputFile* pInputFile = (cEditorInputFile*)pInput->GetInput();
	pInputFile->SetBrowserType(mResType);
	tWStringListIt it = mlstExtensions.begin();
	for(;it!=mlstExtensions.end();++it)
		pInputFile->AddCustomFileType(*it);

	return pInput;
}

//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CUSTOM VAR FILE INPUT
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------------------

cEditorVarInputFile::cEditorVarInputFile(cEditorVarInstance* apVar,
										 iEditorWindow* apWindow,
										 iWidget* apParent) : iEditorVarInput(apVar,
																			  apWindow->CreateInputFile(0,apVar->GetVarType()->GetName(), "", apParent, 100))
																									
{
	cEditorInputFile* pInput = (cEditorInputFile*)mpInput;
	cEditorVarFile* pFile = (cEditorVarFile*)apVar->GetVarType();

	pInput->SetBrowserType(pFile->GetBrowserType());
}


//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------


//--------------------------------------------------------------------
//--------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////
// VAR INSTANCE
/////////////////////////////////////////////////////////////////////

//--------------------------------------------------------------------

cEditorVarInstance::cEditorVarInstance(iEditorVar* apVar)
{
	mpVar = apVar;
}

//--------------------------------------------------------------------

iEditorVarInput* cEditorVarInstance::CreateInput(iEditorWindow* apWindow, iWidget* apParent)
{
	return mpVar->CreateInput(apWindow, apParent, this);
}

//-------------------------------------------------------------------

const tWString& cEditorVarInstance::GetName()
{
	return mpVar->GetName();
}

//-------------------------------------------------------------------

void cEditorVarInstance::SetValue(const tWString& asValue)
{
	msValue = asValue;
}

//-------------------------------------------------------------------
//-------------------------------------------------------------------

/////////////////////////////////////////////////////////////////////
// CLASS
/////////////////////////////////////////////////////////////////////

//-------------------------------------------------------------------

iEditorClass::iEditorClass()
{
}

//-------------------------------------------------------------------

//-------------------------------------------------------------------

bool iEditorClass::AddVariablesFromElement(iEditorClass* apClass, tEditorVarVec& avVars, cXmlElement* apElement)
{
	if(apElement==NULL)
		return false;

	cXmlNodeListIterator it = apElement->GetChildIterator();
	while(it.HasNext())
	{
		cXmlElement* pVarData = it.Next()->ToElement();

		iEditorVar* pVar = apClass->CreateClassSpecificVariableFromElement(pVarData);
		if(pVar)
			avVars.push_back(pVar);
		else
			return false;
	}

	return true;
}

//-------------------------------------------------------------------

iEditorVar* iEditorClass::CreateClassSpecificVariableFromElement(cXmlElement* apElement)
{
	return CreateVariableFromElement(apElement);
}

//-------------------------------------------------------------------

iEditorVar* iEditorClass::CreateVariableFromElement(cXmlElement* apElement)
{
	if(apElement==NULL)
		return NULL;

	iEditorVar* pVar = NULL;

	///////////////////////////////////////////
	// Create Variable according to type
	tString sName = apElement->GetValue();
	if(sName!="Var")
		return NULL;

	tString sType = apElement->GetAttributeString("Type");
	pVar = CreateVariable(sType);

	////////////////////////////////////////////
	// Set up variable
	if(pVar)
		pVar->Create(apElement);

	return pVar;
}

//-------------------------------------------------------------------

iEditorVar* iEditorClass::CreateVariable(const tString& asType)
{
	iEditorVar* pVar = NULL;

	if(asType=="Bool")
		pVar = hplNew(cEditorVarBool, ());

	else if(asType=="Float")
		pVar = hplNew(cEditorVarFloat, ());

	else if(asType=="Int")
		pVar = hplNew(cEditorVarInt, ());

	else if(asType=="String")
		pVar = hplNew(cEditorVarString, ());

	else if(asType=="Vector2")
		pVar = hplNew(cEditorVarVector2f, ());

	else if(asType=="Vector3")
		pVar = hplNew(cEditorVarVector3f, ());

	else if(asType=="Color")
		pVar = hplNew(cEditorVarColor, ());

	else if(asType=="Enum")
		pVar = hplNew(cEditorVarEnum, ());

	else if(asType=="File")
		pVar = hplNew(cEditorVarFile, ());

	else
		pVar = hplNew(cEditorVarString, ());

	return pVar;
}

//-------------------------------------------------------------------

iEditorClass* iEditorClass::GetClassByIdx(const tEditorClassVec& avClasses, int alIdx)
{
	if(alIdx<0 || alIdx>=(int)avClasses.size())
		return NULL;

	return avClasses[alIdx];
}

//-------------------------------------------------------------------

iEditorClass* iEditorClass::GetClassByName(const tEditorClassVec& avClasses, const tString& asName)
{
	for(int i=0;i<(int)avClasses.size();++i)
	{
		iEditorClass* pClass = avClasses[i];
		if(pClass->GetName()==asName)
			return pClass;
	}

	return NULL;
}

//-------------------------------------------------------------------

void iEditorClass::DumpVarsOnInstance(const tEditorVarVec& avVars, cEditorClassInstance* apInstance)
{
	for(int i=0;i<(int)avVars.size();++i)
	{
		iEditorVar* pVar = avVars[i];
		cEditorVarInstance* pVarInstance = pVar->CreateInstance();

		apInstance->AddVarInstance(pVarInstance);
	}
}

//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------

cEditorClassInstance::cEditorClassInstance(iEditorClass* apClass)
{
	mpClass = apClass;
}

cEditorClassInstance::~cEditorClassInstance()
{
	STLDeleteAll(mvVars);
}

//-------------------------------------------------------------------

void cEditorClassInstance::AddVarInstance(cEditorVarInstance* apVar)
{
	// override any previous var with same name
	for(int i=0;i<(int)mvVars.size();++i)
	{
		if(mvVars[i]->GetName() == apVar->GetName())
		{
			hplDelete(mvVars[i]);
			mvVars[i] = apVar;

			return;
		}
	}

	mvVars.push_back(apVar);
}

//-------------------------------------------------------------------

int cEditorClassInstance::GetVarInstanceNum()
{
	return (int)mvVars.size();
}

//-------------------------------------------------------------------

cEditorVarInstance* cEditorClassInstance::GetVarInstance(int alIndex)
{
	if(alIndex<0 || alIndex>=GetVarInstanceNum())
		return NULL;

	cEditorVarInstance* pVar = mvVars[alIndex];

	return pVar;
}

cEditorVarInstance* cEditorClassInstance::GetVarInstance(const tWString& asName)
{
	for(int i=0;i<GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = mvVars[i];
		if(pVar->GetName()==asName)
			return pVar;
	}

	return NULL;
}

//-------------------------------------------------------------------

void cEditorClassInstance::SetVarValue(const tWString& asName, const tWString& asValue)
{
	cEditorVarInstance* pVar = GetVarInstance(asName);
	if(pVar)
	{
		pVar->SetValue(asValue);
	}
}

//-------------------------------------------------------------------

void cEditorClassInstance::Load(cXmlElement* apElement)
{
	cXmlNodeListIterator it = apElement->GetChildIterator();
	while(it.HasNext())
	{
		cXmlElement* pValue = it.Next()->ToElement();
		SetVarValue(cString::To16Char(pValue->GetAttributeString("Name")),
					cString::To16Char(pValue->GetAttributeString("Value")));
	}
}

//-------------------------------------------------------------------

void cEditorClassInstance::Save(cXmlElement* apElement)
{
	for(int i=0;i<GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = GetVarInstance(i);
		cXmlElement* pXmlVar = apElement->CreateChildElement("Var");
		pXmlVar->SetAttributeString("Name", cString::To8Char(pVar->GetName()));
		pXmlVar->SetAttributeString("Value", cString::To8Char(pVar->GetValue()));
	}
}

//-------------------------------------------------------------------

void cEditorClassInstance::LoadValuesFromMap(const tVarValueMap& amapValues)
{
	for(int i=0;i<GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = GetVarInstance(i);
		tVarValueMap::const_iterator it = amapValues.find(pVar->GetName());
		if(it!=amapValues.end())
			pVar->SetValue(it->second);
	}
}

//-------------------------------------------------------------------

void cEditorClassInstance::SaveValuesToMap(tVarValueMap& amapValues)
{
	for(int i=0;i<GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = GetVarInstance(i);
		amapValues[pVar->GetName()] = pVar->GetValue();
	}
}

//-------------------------------------------------------------------

void cEditorClassInstance::LoadFromResourceVarsObject(cResourceVarsObject* apObject)
{
	for(int i=0;i<GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = GetVarInstance(i);
		tString sName = cString::To8Char(pVar->GetName());
		tString sOldValue = cString::To8Char(pVar->GetValue());
		pVar->SetValue(cString::To16Char(apObject->GetVarString(sName, sOldValue)));
	}
}

//-------------------------------------------------------------------

cEditorClassInstance* cEditorClassInstance::CreateCopy()
{
	cEditorClassInstance* pCopy = CreateSpecificCopy();
	pCopy->CopyFromInstance(this);
	
	return pCopy;
}

//-------------------------------------------------------------------

void cEditorClassInstance::CopyFromInstance(cEditorClassInstance* apInstance)
{
	for(int i=0;i<GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = GetVarInstance(i);
		cEditorVarInstance* pVarToCopy = apInstance->GetVarInstance(pVar->GetName());
		if(pVarToCopy)
			pVar->SetValue(pVarToCopy->GetValue());
	}
}

//-------------------------------------------------------------------

cEditorVarInputPanel* cEditorClassInstance::CreateInputPanel(iEditorWindow* apWindow, iWidget* apParent, bool abRows)
{
	cEditorVarInputPanel* pPanel = hplNew(cEditorVarInputPanel,(this));
	pPanel->SetDeployInputsOnRows(abRows);
	pPanel->Create(apWindow, apParent);

	return pPanel;
}

//-------------------------------------------------------------------
//-------------------------------------------------------------------

cEditorVarInputPanel::cEditorVarInputPanel(cEditorClassInstance* apClass)
{
	mpClass = apClass;
	mpHandle = NULL;

	mpCallback = NULL;

	mbDeployInputsOnRows = false;
}

//-------------------------------------------------------------------

cEditorVarInputPanel::~cEditorVarInputPanel()
{
	STLDeleteAll(mvInputs);

	cGuiSet* pSet = mpHandle->GetSet();
	pSet->DestroyWidget(mpHandle, true);
}

//-------------------------------------------------------------------

void cEditorVarInputPanel::Create(iEditorWindow* apWindow, iWidget* apWidget)
{
	cGuiSet* pSet = apWindow->GetSet();
	mpHandle = pSet->CreateWidgetFrame(0,apWidget->GetSize()-4,false, apWidget, false, true);
	mpHandle->SetName("InputPanel");

	cVector3f vPos = cVector3f(0,0,0.1f);

	float fContainerWidth = apWidget->GetSize().x;

	for(int i=0;i<mpClass->GetVarInstanceNum();++i)
	{
		cEditorVarInstance* pVar = mpClass->GetVarInstance(i);
		iEditorVarInput* pInput = pVar->CreateInput(apWindow, mpHandle);
		if(pInput)
		{
			if(mbDeployInputsOnRows)
			{
				if(vPos.x+pInput->GetInput()->GetSize().x> fContainerWidth)
				{
					vPos.x = 0;
					vPos.y += 50;
				}
			}

			pInput->SetPanel(this);

			pInput->GetInput()->SetPosition(vPos);
			pInput->GetInput()->SetLayoutStyle(eEditorInputLayoutStyle_ColumnLabelOnTop);
			pInput->GetInput()->UpdateLayout();

			mvInputs.push_back(pInput);

			if(mbDeployInputsOnRows)
				vPos.x += pInput->GetInput()->GetSize().x + 15.0f;
			else
				vPos.y += pInput->GetInput()->GetSize().y + 10.0f;
		}
	}
}

//-------------------------------------------------------------------

void cEditorVarInputPanel::Update()
{
	for(int i=0;i<(int)mvInputs.size();++i)
	{
		iEditorVarInput* pInput = mvInputs[i];
		pInput->Update();
	}
}

//-------------------------------------------------------------------

void cEditorVarInputPanel::SetCallback(void* apObject, tEditorVarInputPanelCallback apCallback)
{
	mpCallbackObject = apObject;
	mpCallback = apCallback;
}

//-------------------------------------------------------------------

bool cEditorVarInputPanel::RunCallback(iEditorVarInput* apInput)
{
	if(mpCallback==NULL)
		return false;

	return mpCallback(mpCallbackObject, apInput);
}

//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------

